package com.lijin.study.java.other;
/**
 * MchntEx：upop.mchnt.ex：MchntCtrlUtil
 * TODO
 */

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 说明：商户特殊计费方式更新
 *　 
 * @author  shirley.jiang 2012-8-24 下午3:40:07
 */
public class MchntCtrlUtil {
	
	public  void println(String s){
		System.out.println(s);
	}
	 
	//特殊计费类型映射特殊计费方式
	private  int payWayMap(String payType, String payLevel){		 
		if("00".equals(payType) && "0".equals(payLevel))
			return 0;  	//00-无特殊计费类型  0－无特殊计费档次  -> 0-无特殊计费
		 
		if("01".equals(payType) && "0".equals(payLevel))
			return 1;	//01-周期计费 0－月结且按照MCC计费  ->1-月结且按MCC计费
		
		if("01".equals(payType) && "1".equals(payLevel))
			return 2; 	//01-周期计费 1-月结且不按照MCC计费 ->2-月结且不按MCC计费
		
		if("02".equals(payType) && "0".equals(payLevel))
			return 3;	//02-微额打包 0－无特殊计费档次 ->3-日结且微额打包计费
		
		if("03".equals(payType) && "0".equals(payLevel))
			return 4;	//03-固定比例 0－无特殊计费档次 ->4-日结且固定比例模式计费

		return -1;
	}
	
	//读取特殊计费文件文件到MAP
	public  Map<String , Integer>  readSpecialPayFile(String filepath) throws Exception{
		
		if(filepath==null || filepath.trim().equals("")){
			throw new Exception("未指定输入文件路径");
		}
		 
		FileInputStream input = null ;
		InputStreamReader reader= null ;
		BufferedReader br= null ;
		try{
		
			input  = new FileInputStream(filepath);;
			reader = new InputStreamReader(input);
		 	br = new BufferedReader(reader);		 	
		 	
		 	Map<String, Integer > res = new HashMap<String , Integer>();
		 	while(br.ready()){
		 		String line = br.readLine();
		 		if(line != null && !line.trim().equals("")){
		 			String[] rfields = line.split("\\|");		 			 
		 			if(rfields.length != 3){
		 				throw new Exception("文件行格式错误: 商户代码|特殊计费类型|特殊计费档次");
		 			}
		 			int payway = payWayMap(rfields[1].trim(), rfields[2].trim());
		 			if(payway == -1){
		 				println("未找到特殊计费类型对应的计费方式："+ line);
		 				continue;
		 			}
		 			res.put(rfields[0].trim(), payway); 
		 		}
		 	}
		 	println("共"+res.size()+"条记录");
		 	return res;
		}catch(FileNotFoundException fe){			
			throw new Exception("文件["+filepath+"]不存在.");
		}catch(Exception e){
			throw e;
		}finally{
			try {
				if (br != null) {
					br.close();
				}
			} catch (IOException e) {
				 throw e ;
			}
			try {
				if (reader != null) {
					reader.close();
				}
			} catch (IOException e) {
				throw e ;
			}
			br = null;
			reader = null;
		}
		 
	}
	 
	//读取文件到MAP
	public  Map<String , Integer>  readFile(String filepath) throws Exception{
		
		if(filepath==null || filepath.trim().equals("")){
			throw new Exception("未指定输入文件路径");
		}
		 
		FileInputStream input = null ;
		InputStreamReader reader= null ;
		BufferedReader br= null ;
		try{
		
			input  = new FileInputStream(filepath);;
			reader = new InputStreamReader(input);
		 	br = new BufferedReader(reader);		 	
		 	
		 	Map<String, Integer > res = new HashMap<String , Integer>();
		 	while(br.ready()){
		 		String line = br.readLine();
		 		if(line != null && !line.trim().equals("")){
		 			String[] rfields = line.split("\\|");
		 			if(rfields.length != 2){
		 				throw new Exception("文件行格式错误: 商户代码|数值");
		 			}
		 			res.put(rfields[0].trim(), Integer.parseInt(rfields[1].trim()));
		 		}
		 	}
		 	println("共"+res.size()+"条记录");
		 	return res;
		}catch(FileNotFoundException fe){			
			throw new Exception("文件["+filepath+"]不存在.");
		}catch(Exception e){
			throw e;
		}finally{
			try {
				if (br != null) {
					br.close();
				}
			} catch (IOException e) {
				 throw e ;
			}
			try {
				if (reader != null) {
					reader.close();
				}
			} catch (IOException e) {
				throw e ;
			}
			br = null;
			reader = null;
		}
		 
	}
	 
	//将list数据写入脚本文件update_mchnt_ctrl.sql
	public  void writeFile(String filepath, List<String> linedata) throws Exception{
		if(filepath==null || filepath.trim().equals("")){
			throw new Exception("未指定输出文件目录路径");
		}
		File path =  new File(filepath);
		if(!path.isDirectory()){
			path.mkdirs();
		}
		if(filepath.endsWith(File.separator)){
			filepath = filepath + "update_mchnt_ctrl.sql";
		}else{
			filepath = filepath + File.separator + "update_mchnt_ctrl.sql" ;
		}
		BufferedWriter out = null;		 
		try{	   
		    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filepath)));
			for(String line : linedata){
				out.write(line +"\n");
			}
			println("处理结束，生成文件路径： " +filepath);
		}catch(Exception e){
			throw e;
		}finally{
			if(out != null){
				try{
					out.close();
				}catch(IOException e){
					throw new Exception("文件关闭失败");
				}
			}
		}			
	}
	
	//构造更新语句
	public  String buildUpdateSql(String mchntCd, int ctrl3Val, int paywayVal ){
		String upsql = " UPDATE TBL_UPONL_MCHNT_INF SET CTRL_RULE3="+ newMchntCtrl3Val(ctrl3Val, paywayVal )+" WHERE MCHNT_CD = '"+mchntCd+"'; " ;		 
		println(upsql);
		return upsql;
	}
	 
	//运算位值
	private  boolean bitArithmetic(int oriNum, int position, int len) {
		if (position > len - 1) {
			return false;
		}
		return (int) ((oriNum & (1 << (len - position - 1))) >> (len - position - 1)) == 1;
	}
	//数值转换为指定长度的二进制位字符串
	private  String int2BitStr(int oriNum, int len) {
		String bits= "";
		for (int i = 0; i < len; i++) {
			bits  += bitArithmetic(oriNum, i, len)? "1": "0";
		}
		return bits;
	}
	/**
	 * val值在位串中 起始位置：position（0开始，从右往左）,值占位：vallen
	 *  位串总长度: fulllen, 除值位以外其他位上的填充值
	 * @param val	
	 * @param position
	 * @param vallen
	 * @param fulllen
	 * @param fillbit
	 * @return
	 */
	
	//根据原规则3的值 和 特殊计费方式取值，计算出新的规则3值
	private  int newMchntCtrl3Val(int ctrl3Val, int payVal){		
		println("ctl3 = "+ctrl3Val +", payway = "+ payVal); 
		println("1. ctl3 bit = "+int2BitStr(ctrl3Val, 31) +", payway bit  = "+ int2BitStr(payVal, 31));  
		
		ctrl3Val = ctrl3Val & 1677721599; 	//110 0011 1111 1111 1111 1111 1111 1111		
		payVal = payVal << 26; 	//构造值		
		println("2. ctl3 bit = "+int2BitStr(ctrl3Val, 31) +", payway bit  = "+ int2BitStr(payVal, 31) + ", ctrl3的第26-28位置 000,payway移位到第26-28位"); 		 
		
		ctrl3Val = ctrl3Val | payVal;
		println("3. ctl3 bit = "+int2BitStr(ctrl3Val, 31) +", payway bit  = "+ int2BitStr(payVal, 31) +", 3 = 2.ctrl3 | 2.payway "); 
		println("ctl3 = "+ctrl3Val +", payway = "+ payVal); 
		
		return ctrl3Val;
	}
	 

	public static void main( String[] args){
		MchntCtrlUtil ctrlUtil = new MchntCtrlUtil();
		try{
			if(args.length != 3 ){
				throw new Exception("请指定参数：商户控制规则3值文件路径 商户特殊计费值文件路径 更新脚本存放目录路径");
			}			
			String ctrl3File  = args[0];
			String paywayFile  = args[1];
			String savedir  = args[2];
			//1. 读商户控制规则3文件
			Map<String, Integer> ctrl3Map = ctrlUtil.readFile(ctrl3File);
			if(ctrl3Map == null || ctrl3Map.size() <=0){
				throw new Exception("商户控制规则3值文件数据为空。");
			} 
			
			//2. 读商户特殊计费值文件
			Map<String, Integer> paywayMap = ctrlUtil.readSpecialPayFile(paywayFile);
			if(paywayMap == null || paywayMap.size() <=0){
				throw new Exception("商户特殊计费值文件数据为空。");
			}
			
			//3. 控制规则处理，生成更新语句
			List<String> linedata = new ArrayList<String> ();
			for(String upMchntCd : paywayMap.keySet()){
				if(ctrl3Map.keySet().contains(upMchntCd) )
					linedata.add(ctrlUtil.buildUpdateSql(upMchntCd, ctrl3Map.get(upMchntCd).intValue(), paywayMap.get(upMchntCd).intValue()));
			}
			
			//4. 生成更新脚本文件
			ctrlUtil.writeFile(savedir, linedata);
			
		}catch(Exception e){
			ctrlUtil.println(e.getMessage());
		}
		 
	}
	
	
}
